再來和上一篇一樣是介紹一些個人覺得在GraphQL裡比較花俏的操作,雖然說是花俏,但使用的恰當的話同樣可以幫助我們更好的維護程式
其實當初筆者在學習GraphQL時,直接跳過了上一篇和這一篇提到的內容,就開始使用GraphQL建立後端的Server了,也是在一段時間後才回來補這段GraphQL的技術(知識),所以如果讀者非常期待(急著)能看到結果的話,可以直接跳過上一篇和這一篇直接進入實戰環節
還記得我們在query時可能會遇到需要把某一個值傳入嗎?其實,在實作時基本上我們一定都會使用到Variables,下面會舉個例子,如下面這段code,看起來只是很簡單的透過一個id去查詢結果,但實際上如果我們要改變id的內容該怎麼做?
query {
meal(id:"58811ae5-1471-4366-844b-2886b3abccf1"){
id
itemName
price
}
}
在想改變id要怎麼做前,先來看一個例子看完之後會解答原本的疑惑,在實際的應用中,可能會遇到很複雜的query,一次要傳數個不同的值且型別也皆不相同的狀況發生,例如,要做出一個可以同時搜尋金額的區間,餐點的種類,甚至連是否為限量商品的狀況就會變成以下的範例
看完後是否有一種天啊要傳太多東西了吧,此外,還有最重要的問題是,我的值已經寫死了,還是沒辦法改變呀!這完全不符合實際的需求.因此,我們需要使用Variables來幫我們解決
可以看到在左下角的Query variables的區塊內有一個Json格式的內容就是我們可以"彈性的調整"傳入內容,而query內原先的字串,數值等內容已經被替換成了變數(就是看到以$開頭的$minPrice及$category等)
此外Variables還可以加上default值,可能在搜尋時,開發者希望使用者在沒有特別設定金額的情況下,不要推薦一千元以上的餐點,那麼可以這麼做,在maxPrice定義它的default值為1000,不過當下面的Query variables一但有傳值進來的話,那麼傳進來的值將會取代default的1000
範例code:
query (
$minPrice: Int
$maxPrice: Int=1000
$category: String
$isLimitedEdition: Boolean
) {
mealsByMoreCondition(
minPrice: $minPrice
maxPrice: $maxPrice
category: $category
isLimitedEdition: $isLimitedEdition
) {
id
itemName
price
}
}
筆者認為它基本上是在使用query傳入參數時,必然會遇到的問題,default的部分可能還是要真的遇到一些比較特別的情境再使用會比較恰當一些
有沒有遇過一種情境是,前端在同一個頁面時,可能會因為他的使用者權限比較高而打了a+b api,但當他權限比較低時就只要打a api呢?依照傳統的做法,我們可以會再前端寫類似這樣的東西
// 前端
useEffect(() => {
if (user.permissions === 5) {
const mealsResponse = await callMeals({ endpoint: 'api/meals' });
const usersResponse = await callUsers({ endpoint: 'api/users' });
... doSomething
callUsersAndMeals()
} else {
const mealsResponse = await callUsers({ endpoint: 'api/meals' });
... doSomething
}
}, []);
雖然看似很美好,但其實在同一個頁面這種依照權限判斷的事情,我們卻要把它拆分成兩隻api,是有那麼一些麻煩,如果把權限拆的更碎那可能會更可怕,因此我們可以靠Directives來幫我們解決問題
這個是把havePermissions填入false的
這個則是把havePermissions填入true的
範例code:
# Write your query or mutation here
query ($havePermissions:Boolean!){
meals{
id
itemName
}
users @include(if: $havePermissions){
id
firstName
lastName
}
}
就是跟if相反的概念,應該沒有什麼好特別要說明的部分,deprecated就是一個蠻特別的東西了,他可以標記在Schema那邊,讓後續的User在看playGround的時候知道這個field已經被deprecated了,但並不代表不能使用,只是一個提醒。這邊可參考下面的範例
type User {
...
"體重"
weight(unit: WeightUnit = KILOGRAM): Float @deprecated (reason: "It's secret")
}
如此一來我們可以只透過只寫一隻api並且搭配Directives達成我們的目的,筆者自己再開發的時候,蠻習慣用來處理權限或是白名單之類的問題,不過如果當判斷狀況太多太混亂的時候,還是可以考慮把狀況拆清楚,不要過度的濫用導致維護成本增加
這個東西對於熟悉強型別語言的人可能多多少少都有用過,不熟悉的話沒關係,這邊還是會完整的介紹一次
基本上筆者對他的了解為,強烈且硬性的規範傳入值,舉個例子,今天在傳入meal的category時,原先前端的設計只有麵食跟飯食及餃類可以做分類,但使用者卻不知道用了什麼方式傳了一個堅果給後端,讓這值會讓前後端都很難辦,很有可能都會大大的影響到我們的前端的顯示畫面,因此我們需要Enumeration Types來嚴格的把控這件事情
這個時候我們就來使用一個新的Type Declarationenum
,透過以下方式定義完成之後可以來看一下Playground會怎麼告訴我們這件事情
enum CategoryEnum {
"麵食"
pasta
"飯食"
rice
"餃類"
dumpling
}
# input
input MealInput {
itemName: String!
price: Int!
isStopSelling: Boolean!
category:
}
很清楚的告訴我們category只能是pasta,rice或dumpling的其中一個
來故意新增一個nut看看,如我們的預期被擋下來了
透過Enumeration Types讓我們的程式可以更加嚴謹,不會收到一些不理想的值,甚至是前端的工程師在開發時,也可以透過enum定義的內容了解更多事情,不過使用時請一樣要謹慎的使用,畢竟影響範圍很大,可能會讓前端完全沒辦法新增或是更新資料,使用時請務必小心
以上若有錯誤,還請不吝指教.謝謝
基本上GraphQL說到這邊已經差不多了,可以看到它有許多很彈性的語法及應用方式,其實官方網站還有更多,只是筆者也沒有再更深入的了解了,期待未來能看到不同人的分享了解更多神奇的操作
再來就要進入實戰的部分了,不過筆者可能要過一陣子才會補完實戰的部分了.....